package com.nekrashevych;

import java.io.File;
import java.sql.Timestamp;
import java.util.Collection;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.xdoclet.QDoxMetadataProvider;

import com.thoughtworks.qdox.model.JavaClass;
import com.thoughtworks.qdox.model.JavaMethod;

public class MergeUtils {
    public static final Set<String> SIMPLE_TYPES = new HashSet<String>();
    static {
        SIMPLE_TYPES.add(String.class.getSimpleName());
        SIMPLE_TYPES.add(Boolean.class.getSimpleName());
        SIMPLE_TYPES.add(Integer.class.getSimpleName());
        SIMPLE_TYPES.add(Long.class.getSimpleName());
        SIMPLE_TYPES.add(Double.class.getSimpleName());
        SIMPLE_TYPES.add(Short.class.getSimpleName());
        SIMPLE_TYPES.add(Byte.class.getSimpleName());
        SIMPLE_TYPES.add(Character.class.getSimpleName());
        SIMPLE_TYPES.add(Number.class.getSimpleName());
        SIMPLE_TYPES.add(boolean.class.getSimpleName());
        SIMPLE_TYPES.add(int.class.getSimpleName());
        SIMPLE_TYPES.add(long.class.getSimpleName());
        SIMPLE_TYPES.add(double.class.getSimpleName());
        SIMPLE_TYPES.add(short.class.getSimpleName());
        SIMPLE_TYPES.add(byte.class.getSimpleName());
        SIMPLE_TYPES.add(char.class.getSimpleName());

        SIMPLE_TYPES.add(Timestamp.class.getSimpleName());
        SIMPLE_TYPES.add(Date.class.getSimpleName());
    }

    /**
     * gets xdoclet java class to retrieve annotations from
     */
    static JavaClass getJavaClass(File f) {
        QDoxMetadataProvider provider = new QDoxMetadataProvider(f);
        Collection<JavaClass> classes = provider.getMetadata();
        JavaClass clazz = classes.iterator().next();
        return clazz;
    }

    /**
     * gets the file, reads content and invokes manipulate to replace the
     * content that will be writen to the destination file.
     */
    public static void copyAndReplaceContents(ContentReplacer replacer, File source, File destination) throws Exception {
        FileUtils.deleteQuietly(destination);
        JavaClass clazz = getJavaClass(source);
        FileUtils.writeStringToFile(destination, replacer.manipulate(clazz, FileUtils.readFileToString(source)));
        System.out.println("wrote to " + destination.getAbsolutePath());
    }

    /**
     * Removes shitty: ///CLOVER:OFF ///CLOVER:ON
     */
    public static String removeCloverTags(String result) {
        result = StringUtils.remove(result, "///CLOVER:OFF");
        result = StringUtils.remove(result, "///CLOVER:ON");
        return result;
    }

    /**
     * Removes shitty: ejbActivate, ejbPassivate, setSessionContext, ejbRemove
     */
    public static String removeCommonEjbMethods(String result) {
        result = StringMergeUtil.remove(result, "public void setMessageDrive", "}");
        result = StringMergeUtil.remove(result, "public void ejbRemove", "}");
        result = StringMergeUtil.remove(result, "public void ejbActivate", "}");
        result = StringMergeUtil.remove(result, "public void ejbPassivate", "}");
        result = StringMergeUtil.remove(result, "public void setSessionContext", "}");
        result = StringMergeUtil.remove(result, "public final SessionContext getSessionContext", "}");
        result = StringMergeUtil.remove(result, "public SessionContext getSessionContext", "}");
        result = StringMergeUtil.remove(result, "public void ejbCreate", "}");
        return result;
    }

    /**
     * Removes ALL the javadocs from the content.
     */
    public static String removeJavadocs(String result) {
        int length = 0;
        while (result.length() != length) {
            length = result.length();
            result = StringMergeUtil.remove(result, "/**", "*/");
        }
        return result;
    }

    /**
     * If tag is present on javaclazz- returns string, else - null.
     */
    public static String ifTag(JavaClass clazz, String tag, String string) {
        if (clazz.getTagByName(tag) != null) {
            return string;
        }
        return null;
    }

    /**
     * If tag is present on javaMethod- returns string, else - null.
     */
    public static String ifMethodTag(JavaMethod method, String tag, String string) {
        if (method.getTagByName(tag) != null) {
            return string;
        }
        return null;
    }

    public static String ifMethodTagValue(JavaMethod method, String tag, String string) {
        if (method.getTagByName(tag) != null) {
            String value = method.getTagByName(tag).getValue().replace("-", StringUtils.EMPTY);
            if (value != null) {
                return String.format(string, value);
            }
        }
        return null;
    }

    public static String ifMethodTagValues(JavaMethod method, String tag, String string) {
        if (method.getTagByName(tag) != null) {
            String value = method.getTagByName(tag).getValue();
            if (value != null) {
                if (value.contains("\n")) {
                    value = value.replaceAll("\n", ",");
                } else if( value.contains(" ")) {
                    value = value.replaceAll(" ", ",");
                }
                return String.format(string, value);
            }
        }
        return null;
    }
}

interface ContentReplacer {

    public String manipulate(JavaClass clazz, String string);
}